package fsm

import (
	"time"

	"gitee.com/hasika/gotool/generic"
)

type BaseState[State generic.Primitive, Arg any] struct {
}

func (b *BaseState[State, Arg]) DefaultDuration(Arg) time.Duration {
	return -1
}

func (b *BaseState[State, Arg]) OnEnter(arg Arg, timeout bool) (duration StateDuration) {
	return
}

func (b *BaseState[State, Arg]) OnExit(arg Arg, timeout bool) {
}

func (b *BaseState[State, Arg]) GetNextStateOnTimeOut(arg Arg) (state State, duration StateDuration) {
	return
}

func (b *BaseState[State, Arg]) Update(arg Arg) {
}

type SimpleState[State generic.Primitive, Arg any] struct {
	MDefaultDuration       time.Duration
	MOnEnter               func(arg Arg, timeout bool) (duration StateDuration)
	MOnExit                func(arg Arg, timeout bool)
	MGetNextStateOnTimeOut func(arg Arg) (state State)
	MUpdate                func(dt time.Duration, arg Arg)
}

func (s *SimpleState[State, Arg]) DefaultDuration(arg Arg) time.Duration {
	return s.MDefaultDuration
}

func (s *SimpleState[State, Arg]) GetNextStateOnTimeOut(arg Arg) (defaultState State) {
	if s.MGetNextStateOnTimeOut != nil {
		return s.MGetNextStateOnTimeOut(arg)
	}
	return
}

func (s *SimpleState[State, Arg]) OnEnter(arg Arg, b bool) (duration StateDuration) {
	if s.MOnEnter != nil {
		return s.MOnEnter(arg, b)
	}
	return
}

func (s *SimpleState[State, Arg]) OnExit(arg Arg, b bool) {
	if s.MOnExit != nil {
		s.MOnExit(arg, b)
	}
}

func (s *SimpleState[State, Arg]) Update(dt time.Duration, arg Arg) {
	if s.MUpdate != nil {
		s.MUpdate(dt, arg)
	}
}
